﻿using System;
using System.Collections;
using System.Xml;
using Narau.Required_interfaces;

namespace Narau.Common
{
    struct XML_data_info
    {
        public string name_file;
        public XmlDocument xml_doc;
    }

    class Narau : ReqIntf_TreeNodeListener
    {
        public  ReqIntf_View    m_intf_view     { get; set; }
        public  Tema            m_tema_selected { get; set; }

        private XML_data_info   m_info_xml_global;
        private XmlNode         m_xml_global_node;

        private ArrayList       m_xml_temas_list;
        private ArrayList       m_xml_mondai_list;
        private ArrayList       m_mondai_list;
        private ArrayList       m_tema_list;
        private Tema            m_Tema_root;

        private bool            m_bShiken;
        private ShikenGenerator m_ItShikenMondai;
        //[H][B]private Mondai          m_CurrentMondai;
        private ReqIntf_Label   m_Label_Shiken_counter;
        private ReqIntf_Label   m_Label_Mondai_Result;
        private ReqIntf_Label   m_Label_Mondai_Desc;

        private int             m_NextMondai_UID;

        private ScoreTable      m_ScoreTable;

        private int             m_ShikenTick;
        private XmlNode         m_xml_node_ShikenTick;

        public int TICK
        {
            get{ return m_ShikenTick; }
            set
            {
                XmlAttribute xml_attr = m_xml_node_ShikenTick.Attributes["value"];
                if (xml_attr != null)
                {
                    xml_attr.Value = Convert.ToString(value);
                    m_info_xml_global.xml_doc.Save(m_info_xml_global.name_file);
                }
                m_ShikenTick = value;
            }
        }


        //--------------
        // Constructor
        //--------------
        public Narau()
        {
            m_mondai_list = new ArrayList();
            m_tema_list = new ArrayList();
            m_xml_temas_list = new ArrayList();
            m_xml_mondai_list = new ArrayList();
        }
        
        //-----------------------------------------------
        // Carga y proceso de la base de conocimientos
        //-----------------------------------------------
        public void LoadData()
        {
            // xml con los datos globales y de configuración
            LoadGlobalData("NarauGlobal.xml");

            // xml con las descripciones de los temas
            LoadTemaFile("TestTemaList.xml");

            // xml con la lista de ejercicios
            LoadMondaiFile("TestMondaiList.xml");
            CalculateMondaiUIDs();

            // xml con los resultados
            LoadScoreTableFile("ScoreTable.xml");
            SincMondaiScoreTable();

            // Enlace de temas con ejercicios
            foreach (Mondai itEjercicio in m_mondai_list)
            {
                itEjercicio.LinkTemas(m_tema_list);
            }

            // Primer update de las puntuaciones
            m_Tema_root.UpdateData();            
        }

        //--------------------------------------------------------------------------
        // Carga el XML con los datos globales y de configuración de la aplicación 
        //--------------------------------------------------------------------------
        private void LoadGlobalData(string nFile)
        {
            m_info_xml_global.xml_doc = new XmlDocument();
            m_info_xml_global.name_file = nFile;
            m_info_xml_global.xml_doc.Load(nFile);

            m_xml_global_node = m_info_xml_global.xml_doc.SelectSingleNode("global");

            foreach (XmlNode iT_xml_var in m_xml_global_node.ChildNodes)
            {
                if (iT_xml_var.Name == "CurrentTick")
                {
                    m_xml_node_ShikenTick = iT_xml_var;
                    m_ShikenTick = Convert.ToInt32(iT_xml_var.Value); 
                }
            }
        }

        //------------------------------------------------------------
        // Carga los ficheros XML con las descripciones de los temas
        //------------------------------------------------------------
        private void LoadTemaFile(string nFile)
        {
            // Creación del nodo 'root' de Temas
            ReqIntf_TreeNode i_tree_node_root = m_intf_view.TreeIntf.NewTreeNode();
            m_Tema_root = new Tema(null, i_tree_node_root);
            m_Tema_root.Title = "Temas";
            m_Tema_root.Info = "Arbol con los distintos temas y subtemas de aprendizaje que contiene la base de datos de la aplicación.";
            i_tree_node_root.Listener = this;

            // Carga de temas desde XML y construcción del arbol de temas
            XmlDocument xml_temas = new XmlDocument();
            xml_temas.Load(nFile);

            XmlNode xml_list_temas = xml_temas.SelectSingleNode("list");
            foreach (XmlNode xml_tema in xml_list_temas.ChildNodes)
            {
                if (xml_tema.Name == "tema")
                {
                    Tema new_tema = ParseNodoTema(xml_tema, m_Tema_root, i_tree_node_root);
                }
            }

            XML_data_info xml_info = new XML_data_info();
            xml_info.xml_doc = xml_temas;
            xml_info.name_file = nFile;

            m_xml_temas_list.Add(xml_info);
        }

        //-------------------
        // Método recursivo
        //-------------------
        private Tema ParseNodoTema(XmlNode xml_tema, Tema tema_parent, ReqIntf_TreeNode tree_node_parent)
        {
            ReqIntf_TreeNode ri_TreeNode = null;
            if (tree_node_parent == null)
            {
                ri_TreeNode = m_intf_view.TreeIntf.NewTreeNode();
            }
            else
            {
                ri_TreeNode = tree_node_parent.NewChildTreeNode();
            }

            Tema new_tema = new Tema(tema_parent, ri_TreeNode);
            new_tema.ParserXML(xml_tema);

            m_tema_list.Add(new_tema);

            ri_TreeNode.Listener = this;

            // Busqueda de temas hijos y creación recursiva
            foreach (XmlNode xml_node_sub_tema in xml_tema.ChildNodes)
            {
                if (xml_node_sub_tema.Name == "tema")
                {
                    ParseNodoTema(xml_node_sub_tema, new_tema, ri_TreeNode);
                }
            }

            return new_tema;
        }

        //-------------------------------------------------------------------------------------
        // Carga un fichero XML con descripciones de ejercicios y los añade a la lista global 
        //-------------------------------------------------------------------------------------
        private void LoadMondaiFile(string nFile)
        {
            XmlDocument xml_data = new XmlDocument();
            xml_data.Load(nFile);

            XmlNode xml_mondai_list = xml_data.SelectSingleNode("list");

            // Se recorre la lista de ejercicios del fichero XML
            foreach (XmlNode xml_mondai in xml_mondai_list)
            {
                Mondai new_mondai = new Mondai();
                new_mondai.XmlKaraTsukuru(xml_mondai);
                m_mondai_list.Add(new_mondai);
            }

            XML_data_info xml_info = new XML_data_info();
            xml_info.xml_doc = xml_data;
            xml_info.name_file = nFile;

            m_xml_mondai_list.Add(xml_info);
        }

        //-------------------------------------------------------------------------------
        // Calcula el UID siguiente válido y asigna UIDs a los ejercicios que no tienen
        //-------------------------------------------------------------------------------
        private void CalculateMondaiUIDs()
        {
            m_NextMondai_UID = 0;
            foreach (Mondai iTMondai in m_mondai_list)
            {
                if (m_NextMondai_UID <= iTMondai.UID)
                {
                    m_NextMondai_UID = iTMondai.UID + 1;
                }
            }

            foreach (Mondai iTMondai in m_mondai_list)
            {
                if (iTMondai.UID == 0)
                {
                    iTMondai.UID = m_NextMondai_UID;
                    m_NextMondai_UID++;
                }
            }

            foreach (XML_data_info itXml in m_xml_mondai_list)
            {
                itXml.xml_doc.Save(itXml.name_file);
            }
        }

        //--------------------------------------------------------------
        // Carga el xml con la información de resultados de ejercicios
        //--------------------------------------------------------------
        private void LoadScoreTableFile(string nFile)
        {
            m_ScoreTable = new ScoreTable(nFile);
        }

        //--------------------------------------
        // Relaciona ejercicios con resultados
        //--------------------------------------
        private void SincMondaiScoreTable()
        {
            foreach (Mondai iT_mondai in m_mondai_list)
            {
                m_ScoreTable.SyncMondai(iT_mondai); 
            }
            m_ScoreTable.UpdateFile();
        }

        //----------------------------------------------------------------
        // Presenta al usuario todos los ejercicios relacionados con el
        // tema seleccionado, y sus temas hijos, recursivamente
        //----------------------------------------------------------------
        public void ShikenSuru()
        {
            if (m_bShiken == false)
            {
                m_intf_view.PanelUpIntf.Clear();
                m_Label_Shiken_counter = null;
                m_Label_Mondai_Desc = null;
                m_Label_Mondai_Result = null;

                TICK = TICK + 1;

                m_bShiken = true;

                m_ItShikenMondai = new ShikenGenerator();
                //[H][B]m_ItShikenMondai.Begin();

                m_tema_selected.BuildShiken(m_ItShikenMondai);


                ReqIntf_Label label_1 = m_intf_view.PanelUpIntf.AddLabel();
                label_1.SetFont(ENR_FontType.NFT_NIHONGO);
                label_1.SetBorder(true);
                label_1.SetText("EXAMEN");

                m_Label_Shiken_counter = m_intf_view.PanelUpIntf.AddLabel();
                m_Label_Shiken_counter.SetFont(ENR_FontType.NFT_NIHONGO);

                ReqIntf_Label separator = m_intf_view.PanelUpIntf.AddLabel();
                separator.SetFont(ENR_FontType.NFT_NIHONGO);
                separator.SetBorder(false);
                separator.SetText(" ");

                m_Label_Mondai_Desc = m_intf_view.PanelUpIntf.AddLabel();
                m_Label_Mondai_Desc.SetFont(ENR_FontType.NFT_NIHONGO);
                m_Label_Mondai_Desc.SetBorder(false);
                m_Label_Mondai_Desc.SetText("Examen generado. Selecciona 'siguiente pregunta' para empezar");

                ReqIntf_Label separator_2 = m_intf_view.PanelUpIntf.AddLabel();
                separator_2.SetFont(ENR_FontType.NFT_NIHONGO);
                separator_2.SetBorder(false);
                separator_2.SetText(" ");

                m_Label_Mondai_Result = m_intf_view.PanelUpIntf.AddLabel();
                m_Label_Mondai_Result.SetBorder(true);
                m_Label_Mondai_Result.SetFont(ENR_FontType.NFT_NIHONGO);

                UpdateView();
            }
        }

        //------------------------------------------------------------------------------------
        // Presenta el siguiente ejercicio de la lista "examen" creada en el ShikenGenerator
        //------------------------------------------------------------------------------------
        public void NextMondai()
        {
            if ((m_bShiken == true) && (m_ItShikenMondai != null))
            {
                ShikenGenerator.EShikenStatus shiken_status = m_ItShikenMondai.Step(TICK);
                switch (shiken_status)
                {
                    case ShikenGenerator.EShikenStatus.NEW_MONDAI:
                        {
                            // Un nuevo ejercicio
                            m_intf_view.PanelDownIntf.Clear();
                            m_Label_Mondai_Result.SetText("　");
                            m_ItShikenMondai.ActMondai.Suru(m_Label_Mondai_Desc, m_intf_view.PanelDownIntf);
                            break;
                        }
                    case ShikenGenerator.EShikenStatus.CHECK_MONDAI:
                        {
                            // El último ejercicio corregido
                            //[H]m_ItShikenMondai.ActMondai.ShowResult();
                            if (m_ItShikenMondai.ActMondai.IsOK())
                            {
                                m_Label_Mondai_Result.SetText("BIEN");
                            }
                            else
                            {
                                m_Label_Mondai_Result.SetText("MAL");
                            }
                            UpdateView();
                            break;
                        }
                    case ShikenGenerator.EShikenStatus.OWARI:
                        {
                            // Examen finalizado
                            m_bShiken = false;
                            m_intf_view.PanelDownIntf.Clear();
                            m_Label_Mondai_Desc.SetText("¡¡EXAMEN FINALIZADO!!");

                            // Grabación a fichero de la tabla de resultados de los ejercicios
                            m_ScoreTable.UpdateFile();
                            break;
                        }
                }

                /*m_CurrentMondai = m_ItShikenMondai.GetNextMondai(TICK);
                if (m_CurrentMondai != null)
                {
                    m_intf_view.PanelDownIntf.Clear();
                    m_CurrentMondai.Suru(m_Label_Mondai_Desc, m_intf_view.PanelDownIntf); 
                }
                else
                {
                    // Examen finalizado
                    m_bShiken = false;
                    m_intf_view.PanelDownIntf.Clear();
                    m_Label_Mondai_Desc.SetText("¡¡EXAMEN FINALIZADO!!");

                    // Grabación a fichero de la tabla de resultados de los ejercicios
                    m_ScoreTable.UpdateFile();
                }*/

                // Actualización de los datos en el arbol de temas
                m_Tema_root.UpdateData();

                UpdateView();
            }
        }

        //-------------------------------------------------
        // Actualiza el contador de ejercicios realizados
        //-------------------------------------------------
        private void UpdateView()
        {
            if (m_Label_Shiken_counter != null)
            {
                string out_string = Convert.ToString(m_ItShikenMondai.IdxMondai);
                out_string += " / ";
                out_string += Convert.ToString(m_ItShikenMondai.NumMondai);
                out_string += "  Bien: " + Convert.ToString(m_ItShikenMondai.NumOK);
                out_string += "  Mal: " + Convert.ToString(m_ItShikenMondai.NumFail);
                
                //[H][B]
                /*if (m_ItShikenMondai.CurrMondai > 1)
                {
                    out_string += "  Ultimo: ";
                    if (m_ItShikenMondai.LastOK == true)
                    {
                        out_string += "BIEN";
                    }
                    else
                    {
                        out_string += "MAL";
                    }
                }*/

                m_Label_Shiken_counter.SetText(out_string);
            }


        }

        //----------------------------------------------------
        // Implementación del interface de TreeNodeListener
        //----------------------------------------------------
        #region Intf_TreeNodeListener Members

            public void OnSelect(object link_obj)
            {
                if (m_bShiken == false)
                {
                    // [H]Luego hacerlo con modos de pantalla
                    ReqIntf_Label tema_label;
                    //[H]ReqIntf_Label tema_score;
                    ReqIntf_Label tema_texto;

                    m_intf_view.PanelUpIntf.Clear();
                    
                    tema_label = m_intf_view.PanelUpIntf.AddLabel();
                    tema_label.SetBorder(true);
                    tema_label.SetFont(ENR_FontType.NFT_NIHONGO);

                    //[H]
                    /*tema_score = m_intf_view.PanelUpIntf.AddLabel();
                    tema_score.SetBorder(false);
                    tema_score.SetFont(ENR_FontType.NFT_NIHONGO);*/

                    tema_texto = m_intf_view.PanelUpIntf.AddLabel();
                    tema_texto.SetBorder(false);
                    tema_texto.SetFont(ENR_FontType.NFT_NIHONGO);

                    m_tema_selected = link_obj as Tema;
                    
                    string cadena = "TEMA: " + m_tema_selected.FullName;
                    tema_label.SetText(cadena);

                    tema_texto.SetText(m_tema_selected.Info);
                }
            }

        #endregion
    }
}
